﻿
#include <stdio.h>
#include <string.h>

const char* types[] = {"Decimal",
                       "Int64",
                       "Int32",
                       "Int16",
                       "SByte",
                       "UInt64",
                       "UInt32",
                       "UInt16",
                       "Byte",
                       "Single",
                       "Double",
                       "String"};
#define ARRAY_SIZE_0 "        Return If(i Is Nothing, uint32_0, CUInt(i.Length()))\n"
#define ARRAY_SIZE_2 "        Return If(i Is Nothing, 0, i.Length())\n"
#define ARRAY_LONG_SIZE_0 "        Return If(i Is Nothing, uint32_0, CULng(i.LongLength()))\n"
#define IS_EMPTY_ARRAY_0 "        Return i Is Nothing OrElse i.Length() = 0\n"
#define ARRAY_SIZE_1 "        Return If(i Is Nothing, uint32_0, CUInt(i.GetLength(0)))\n"
#define ARRAY_SIZE_3 "        Return If(i Is Nothing, 0, i.GetLength(0))\n"
#define ARRAY_LONG_SIZE_1 "        Return If(i Is Nothing, uint32_0, CULng(i.GetLongLength(0)))\n"
#define IS_EMPTY_ARRAY_1 "        Return i Is Nothing OrElse i.GetLength(0) = 0\n"
#define COMPARE_ARRAY_0 "        assert(array_size(first) >= first_start + len)\n" \
                        "        assert(array_size(second) >= second_start + len)\n" \
                        "        Dim fs As Int32 = 0\n" \
                        "        fs = CInt(first_start)\n" \
                        "        Dim ss As Int32 = 0\n" \
                        "        ss = CInt(second_start)\n" \
                        "        For i As Int32 = 0 To CInt(len) - 1\n" \
                        "            Dim cmp As Int32 = 0\n" \
                        "            cmp = compare(first(i + fs), second(i + ss))\n" \
                        "            If cmp <> 0 Then\n" \
                        "                Return cmp\n" \
                        "            End If\n" \
                        "        Next\n" \
                        "        Return 0\n"
#define COMPARE_ARRAY_1 "        Return memcmp(first, uint32_0, second, uint32_0, len)\n"
#define COMPARE_ARRAY_2 "        Dim ll As UInt32 = 0\n" \
                        "        Dim rl As UInt32 = 0\n" \
                        "        ll = array_size(first)\n" \
                        "        rl = array_size(second)\n" \
                        "        If ll <> rl Then\n" \
                        "            Return compare(ll, rl)\n" \
                        "        Else\n" \
                        "            Return memcmp(first, second, ll)\n" \
                        "        End If\n"
#define TO_STRINGS_1 "        If isemptyarray(i) Then\n" \
                     "            Return Nothing\n" \
                     "        Else\n" \
                     "            Dim r() As String = Nothing\n" \
                     "            ReDim r(array_size_i(i) - 1)\n" \
                     "            For j As Int32 = 0 To array_size_i(i) - 1\n" \
                     "                r(j) = Convert.ToString(i(j))\n" \
                     "            Next\n" \
                     "            Return r\n" \
                     "        End If\n"
#define TO_STRINGS_2 "        Dim r() As String = Nothing\n" \
                     "        ReDim r(array_size_i(j))\n" \
                     "        r(0) = Convert.ToString(i)\n" \
                     "        For k As Int32 = 0 To array_size_i(j) - 1\n" \
                     "            r(k + 1) = Convert.ToString(j(k))\n" \
                     "        Next\n" \
                     "        Return r\n"
#define START_WITH   "        If array_size(first) < array_size(second) Then\n" \
                     "            Return False\n" \
                     "        Else\n" \
                     "            Return memcmp(first, second, array_size(second)) = 0\n" \
                     "        End If\n"
#define END_WITH     "        If array_size(first) < array_size(second) Then\n" \
                     "            Return False\n" \
                     "        Else\n" \
                     "            Return memcmp(first, array_size(first) - array_size(second), second, uint32_0, array_size(second)) = 0\n" \
                     "        End If\n"

int main(int argc, char* argv[])
{
    if(argc < 2) printf("need a parameter for output file.\n");
    else
    {
        FILE* fo = fopen(argv[1], "w");
        fputs("\n'this file is generated by osi/root/codegen/array/array.exe"
              "\n'so edit the osi/root/codegen/array/array.cpp instead of this file\n"
              "\nOption Strict On\n"
              "\nImports System.Runtime.CompilerServices\n"
              "\nImports osi.root.constants\n"
              "\n\nPublic Module _array\n\n"
              "#If Not DEBUG Then\n\n", fo);
        for(int i = 0; i < sizeof(types) / sizeof(types[0]); i++)
        {
            fprintf(fo,
                    "    Public Function array_size(ByVal i() As %s) As UInt32\n"
                    ARRAY_SIZE_0
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function array_size_i(ByVal i() As %s) As Int32\n"
                    ARRAY_SIZE_2
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function array_long_size(ByVal i() As %s) As UInt64\n"
                    ARRAY_LONG_SIZE_0
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function isemptyarray(ByVal i() As %s) As Boolean\n"
                    IS_EMPTY_ARRAY_0
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function array_size(ByVal i(,) As %s) As UInt32\n"
                    ARRAY_SIZE_1
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function array_size_i(ByVal i(,) As %s) As Int32\n"
                    ARRAY_SIZE_3
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function array_long_size(ByVal i(,) As %s) As UInt64\n"
                    ARRAY_LONG_SIZE_1
                    "    End Function\n\n",
                    types[i]);

            fprintf(fo,
                    "    Public Function isemptyarray(ByVal i(,) As %s) As Boolean\n"
                    IS_EMPTY_ARRAY_1
                    "    End Function\n\n",
                    types[i]);
            fprintf(fo,
                    "    Public Function memcmp(ByVal first() As %s,\n"
                    "                           ByVal first_start As UInt32,\n"
                    "                           ByVal second() As %s,\n"
                    "                           ByVal second_start As UInt32,\n"
                    "                           ByVal len As UInt32) As Int32\n"
                    COMPARE_ARRAY_0
                    "    End Function\n\n",
                    types[i],
                    types[i]);
            fprintf(fo,
                    "    Public Function memcmp(ByVal first() As %s,\n"
                    "                           ByVal second() As %s,\n"
                    "                           ByVal len As UInt32) As Int32\n"
                    COMPARE_ARRAY_1
                    "    End Function\n\n",
                    types[i],
                    types[i]);
            fprintf(fo,
                    "    Public Function memcmp(ByVal first() As %s,\n"
                    "                           ByVal second() As %s) As Int32\n"
                    COMPARE_ARRAY_2
                    "    End Function\n\n",
                    types[i],
                    types[i]);
            fprintf(fo,
                    "    <Extension()> Public Function to_strings(ByVal i() As %s) As String()\n"
                    TO_STRINGS_1
                    "    End Function\n\n",
                    types[i]);
            fprintf(fo,
                    "    <Extension()> Public Function to_strings(ByVal i As %s, ByVal ParamArray j() As %s) As String()\n"
                    TO_STRINGS_2
                    "    End Function\n\n",
                    types[i],
                    types[i]);
            fprintf(fo,
                    "    <Extension()> Public Function start_with(ByVal first() As %s, ByVal second() As %s) As Boolean\n"
                    START_WITH
                    "    End Function\n\n",
                    types[i],
                    types[i]);
            fprintf(fo,
                    "    <Extension()> Public Function end_with(ByVal first() As %s, ByVal second() As %s) As Boolean\n"
                    END_WITH
                    "    End Function\n\n",
                    types[i],
                    types[i]);
        }
        fputs("#End If\n\n", fo);

        fputs("    Public Function array_size(Of T)(ByVal i() As T) As UInt32\n"
              ARRAY_SIZE_0
              "    End Function\n\n",
              fo);

        fputs("    Public Function array_size_i(Of T)(ByVal i() As T) As Int32\n"
              ARRAY_SIZE_2
              "    End Function\n\n",
              fo);

        fputs("    Public Function array_long_size(Of T)(ByVal i() As T) As UInt64\n"
              ARRAY_LONG_SIZE_0
              "    End Function\n\n",
              fo);

        fputs("    Public Function isemptyarray(Of T)(ByVal i() As T) As Boolean\n"
              IS_EMPTY_ARRAY_0
              "    End Function\n\n",
              fo);

        fputs("    Public Function array_size(Of T)(ByVal i(,) As T) As UInt32\n"
              ARRAY_SIZE_1
              "    End Function\n\n",
              fo);

        fputs("    Public Function array_size_i(Of T)(ByVal i(,) As T) As Int32\n"
              ARRAY_SIZE_3
              "    End Function\n\n",
              fo);

        fputs("    Public Function array_long_size(Of T)(ByVal i(,) As T) As UInt64\n"
              ARRAY_LONG_SIZE_1
              "    End Function\n\n",
              fo);

        fputs("    Public Function isemptyarray(Of T)(ByVal i(,) As T) As Boolean\n"
              IS_EMPTY_ARRAY_1
              "    End Function\n\n",
              fo);

        fputs("    Public Function memcmp(Of T)(ByVal first() As T,\n"
              "                                 ByVal first_start As UInt32,\n"
              "                                 ByVal second() As T,\n"
              "                                 ByVal second_start As UInt32,\n"
              "                                 ByVal len As UInt32) As Int32\n"
              COMPARE_ARRAY_0
              "    End Function\n\n",
              fo);
        fputs("    Public Function memcmp(Of T)(ByVal first() As T,\n"
              "                                 ByVal second() As T,\n"
              "                                 ByVal len As UInt32) As Int32\n"
              COMPARE_ARRAY_1
              "    End Function\n\n",
              fo);
        fputs("    Public Function memcmp(Of T)(ByVal first() As T,\n"
              "                                 ByVal second() As T) As Int32\n"
              COMPARE_ARRAY_2
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function to_strings(Of T)(ByVal i() As T) As String()\n"
              TO_STRINGS_1
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function to_strings(Of T)(ByVal i As T, ByVal ParamArray j() As T) As String()\n"
              TO_STRINGS_2
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function start_with(Of T)(ByVal first() As T, ByVal second() As T) As Boolean\n"
              START_WITH
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function end_with(Of T)(ByVal first() As T, ByVal second() As T) As Boolean\n"
              END_WITH
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function to_strings(ByVal i() As Object) As String()\n"
              TO_STRINGS_1
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function to_strings(ByVal i As Object, ByVal ParamArray j() As Object) As String()\n"
              TO_STRINGS_2
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function start_with(ByVal first() As Object, ByVal second() As Object) As Boolean\n"
              START_WITH
              "    End Function\n\n",
              fo);
        fputs("    <Extension()> Public Function end_with(ByVal first() As Object, ByVal second() As Object) As Boolean\n"
              END_WITH
              "    End Function\n\n",
              fo);

        fputs("End Module\n", fo);
        fclose(fo);
    }
}

